#include "XCxcD3D11Drawer.h"
#include <cmath>


XCxcD3D11Drawer::XCxcD3D11Drawer()
{
}

XCxcD3D11Drawer::~XCxcD3D11Drawer()
{
}

void XCxcD3D11Drawer::initializeScene()
{
	D3D11_INPUT_ELEMENT_DESC layout[] = 
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	D3DX11CompileFromFile(L"Effects.fx", NULL, NULL, "VS", "vs_5_0", 0, 0, NULL, &vertexShaderBuffer, NULL, NULL);
	D3DX11CompileFromFile(L"Effects.fx", NULL, NULL, "PS", "ps_5_0", 0, 0, NULL, &pixelShaderBuffer, NULL, NULL);
	device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &vertexShader);
	device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &pixelShader);
	context->VSSetShader(vertexShader, NULL, NULL);
	context->PSSetShader(pixelShader, NULL, NULL);
	device->CreateInputLayout(layout, 2, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &vertexLayout);
	context->IASetInputLayout(vertexLayout);

	Vertex anVert[] =
	{
		{ XMFLOAT3(0.0f, 0.0f, 0.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(3.0f, 0.0f, 0.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(0.0f, 0.0f, 0.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(0.0f, 3.0f, 0.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(0.0f, 0.0f, 00.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(0.10f, 0.0f, 3.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
	};
	XCreateSimpleBuffer(D3D11_BIND_VERTEX_BUFFER, anVert, sizeof(anVert), &anchorVertexBuffer);

	Vertex vertices[] =
	{
		{ XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
		{ XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },
		{ XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) },
		{ XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
		{ XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) },
		{ XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
	};
	XCreateSimpleBuffer(D3D11_BIND_VERTEX_BUFFER, vertices, sizeof(vertices), &triangleVertexBuffer);

	// Create index buffer
	DWORD indices[] =
	{
		//
		3,1,0,
		2,1,3,
		//
		0,5,4,
		1,5,0,
		//
		3,4,7,
		0,4,3,
		//
		1,6,5,
		2,6,1,
		//
		2,7,6,
		3,7,2,
		//
		6,4,5,
		7,4,6,
	};
	XCreateSimpleBuffer(D3D11_BIND_INDEX_BUFFER, indices, sizeof(indices), &triangleIndexBuffer);
	context->IASetIndexBuffer(triangleIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

	context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	XCreateSimpleBufferNull(D3D11_BIND_CONSTANT_BUFFER, sizeof(ConstantBuffer), &constantBuffer);

	world = XMMatrixIdentity();
	
	XMVECTOR eye = XMVectorSet(0.0f, 0.0f, 3.0f, 0.0f);
	XMVECTOR at = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
	XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
	view = XMMatrixLookAtLH(eye, at, up);
	
	projection = XMMatrixPerspectiveFovLH(XM_PIDIV2, width / (float)height, 0.01f, 100.0f);

	// draw ball
	const float PI = 3.1415926535f;
	int cntCP = 10;
	cntBallPoints = (2 * cntCP + 1) * cntCP;
	float seed = 1.0f / (float)(cntCP);
	Vertex *vecBall = new Vertex[cntBallPoints];
	for (int i = 0; i < cntCP * 2 + 1; i++) {
		for (int j = 0; j < cntCP; j++) {
			float z = 1.0f - i * seed;
			float r = sqrt(1.0f - z * z);
			float x = r * cos(2 * PI * (j / (float)cntCP));
			float y = r * sin(2 * PI * (j / (float)cntCP));
			static int times = 0;
			times++;

			if (times == 3) {
				times = 0;
			}

			float red, g, b;
			if (times == 0) {
				red = 1.0f;
				g = 0.0f;
				b = 0.0f;
			} else if (times == 1) {
				red = 0.0f;
				g = 1.0f;
				b = 0.0f;
			} else {
				red = 0.0f;
				g = 0.0f;
				b = 1.0f;
			}

			vecBall[i * cntCP + j].set(x, y, z, red, g, b, 1.0f);
		}
	}
	XCreateSimpleBuffer(D3D11_BIND_VERTEX_BUFFER, vecBall, sizeof(Vertex) * cntBallPoints, &ballVertexBuffer);

	cntBallIndices = 0;
	DWORD *indexBall = new DWORD[cntCP * 2 * cntCP * 6];
	for (int i = 0; i < cntCP * 2; i++) {
		for (int j = 0; j < cntCP; j++) {
			indexBall[cntBallIndices++] = i * cntCP + j;
			indexBall[cntBallIndices++] = (i + 1) * cntCP + j;
			indexBall[cntBallIndices++] = (i + 1) * cntCP + ((j + 1) % cntCP);
			
			indexBall[cntBallIndices++] = i * cntCP + (j + 1) % cntCP;
			indexBall[cntBallIndices++] = i * cntCP + j;
			indexBall[cntBallIndices++] = (i + 1) * cntCP + ((j + 1) % cntCP);

		}
	}
	XCreateSimpleBuffer(D3D11_BIND_INDEX_BUFFER, indexBall, sizeof(DWORD) * cntBallIndices, &ballIndexBuffer);

}

void XCxcD3D11Drawer::update()
{
}

void XCxcD3D11Drawer::draw()
{
	float backColors[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	context->ClearRenderTargetView(renderTargetView, backColors);
	context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 10.0f, 0);

	for (int i = 0; i < 1; i++) {
		ConstantBuffer cb;
		cb.Projection = XMMatrixTranspose(projection);
		cb.View = XMMatrixTranspose(view);
		cb.World = XMMatrixTranspose(/* XMMatrixTranslation(2.5f * i, 0.0f, 0.0f) * */ world);

		context->UpdateSubresource(constantBuffer, 0, NULL, &cb, 0, 0);
		context->VSSetConstantBuffers(0, 1, &constantBuffer);

	//	drawAnchors();
		drawBall();

	//	UINT stride = sizeof(Vertex);
	//	UINT offset = 0;
	//	context->IASetVertexBuffers(0, 1, &triangleVertexBuffer, &stride, &offset);
	//	context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	//	context->DrawIndexed(36, 0, 0);
	}


	swapChain->Present(0, 0);
}

void XCxcD3D11Drawer::rotateY(float ang)
{
	XMVECTOR rotaxis = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
	world *= XMMatrixRotationAxis(rotaxis, ang);

}

void XCxcD3D11Drawer::rotateX(float ang)
{
	XMVECTOR rotaxis = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);
	world *= XMMatrixRotationAxis(rotaxis, ang);
}

void XCxcD3D11Drawer::rotateZ(float ang)
{
	XMVECTOR rotaxis = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
	world *= XMMatrixRotationAxis(rotaxis, ang);
}

void XCxcD3D11Drawer::drawAnchors()
{
	UINT stride = sizeof(Vertex);
	UINT offset = 0;
	context->IASetVertexBuffers(0, 1, &anchorVertexBuffer, &stride, &offset);
	context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
	context->Draw(6, 0);
}

void XCxcD3D11Drawer::drawBall()
{
	UINT stride = sizeof(Vertex);
	UINT offset = 0;
	context->IASetVertexBuffers(0, 1, &ballVertexBuffer, &stride, &offset);
	context->IASetIndexBuffer(ballIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
	context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);
//	context->Draw(cntBallPoints, 0);
	context->DrawIndexed(cntBallIndices, 0, 0);
}
